home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / internet / html-related / hsc / source / hsclib / defattr.c < prev    next >
C/C++ Source or Header  |  1996-09-12  |  13KB  |  503 lines

  1. /*
  2.  * hsclib/defattr.c
  3.  *
  4.  * functions to define new attribute
  5.  * and manipulate attribute lists
  6.  *
  7.  * Copyright (C) 1995,96  Thomas Aglassinger
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22.  *
  23.  * updated:  4-Aug-1996
  24.  * created:  6-Jan-1995
  25.  */
  26.  
  27. #define NOEXTERN_HSCLIB_DEFATTR
  28.  
  29. #include "hsclib/inc_base.h"
  30.  
  31. #include "hsclib/defattr.h"
  32. #include "hsclib/eval.h"
  33. #include "hsclib/input.h"
  34.  
  35. /*
  36.  *-------------------------------------
  37.  * misc. functions
  38.  *-------------------------------------
  39.  */
  40. static BYTE str2vartype(STRPTR s)
  41. {
  42.     BYTE vartype = VT_NONE;
  43.  
  44.     if (!upstrcmp(VT_STR_URI, s))
  45.         vartype = VT_URI;
  46.     else if (!upstrcmp(VT_STR_STRING, s))
  47.         vartype = VT_STRING;
  48.     else if (!upstrcmp(VT_STR_BOOL, s))
  49.         vartype = VT_BOOL;
  50.     else if (!upstrcmp(VT_STR_NUM, s))
  51.         vartype = VT_NUM;
  52.     else if (!upstrcmp(VT_STR_ENUM, s))
  53.         vartype = VT_ENUM;
  54.     else if (!upstrcmp(VT_STR_ID, s))
  55.         vartype = VT_ID;
  56.     else if (!upstrcmp(VT_STR_COLOR, s))
  57.         vartype = VT_COLOR;
  58.  
  59.     return (vartype);
  60. }
  61.  
  62. /*
  63.  * check_varlist: check for required attributes missing
  64.  *
  65.  * result: TRUE, if all attributes ok
  66.  */
  67. static BOOL check_reqvar(HSCPRC * hp, HSCATTR * var)
  68. {
  69.     BOOL ok = TRUE;
  70.  
  71.     if ((var->varflag & VF_REQUIRED)
  72.         && (!var->text))
  73.     {
  74.         hsc_message(hp, MSG_MISS_REQ_ATTR,
  75.                     "required %A missing", var);
  76.         ok = FALSE;
  77.     }
  78.  
  79.     return (ok);
  80. }
  81.  
  82. BOOL check_varlist(HSCPRC * hp, DLLIST * varlist)
  83. {
  84.     DLNODE *nd = varlist->first;
  85.     BOOL ok = TRUE;
  86.  
  87.     while (nd)
  88.     {
  89.         ok &= check_reqvar(hp, (HSCATTR *) (nd->data));
  90.         nd = nd->next;
  91.     }
  92.  
  93.     return (ok);
  94. }
  95.  
  96. /*
  97.  *-------------------------------------
  98.  * define a new var from input file
  99.  *-------------------------------------
  100.  */
  101.  
  102. /*
  103.  * read_enum_str
  104.  *
  105.  * sidefx: modifies tmpstr
  106.  */
  107. static BOOL read_enum_str(HSCPRC * hp, HSCATTR * var)
  108. {
  109.     HSCATTR *attr = new_hscattr(PREFIX_TMPATTR "enumerator");
  110.     attr->vartype = VT_STRING;
  111.  
  112.     /* store enumstr in var-struct */
  113.     if (eval_expression(hp, attr, NULL))
  114.     {
  115.         DDA(fprintf(stderr, DHL "  enum: %s\n", estr2str(hp->tmpstr)));
  116.         var->enumstr = strclone(get_vartext(attr));
  117.     }
  118.  
  119.     del_hscattr(attr);
  120.  
  121.     return ((BOOL) (!hp->fatal));
  122. }
  123.  
  124. /*
  125.  * check_attr_option
  126.  *
  127.  * check if a attribute-option-string is equal to an id/short id.
  128.  * if so, set the corresponding option value within the attribute.
  129.  *
  130.  * params: option..option string to check for (read from input)
  131.  *         attr....attribute to update option value for
  132.  *         id......id string of option (eg "REQUIRED")
  133.  *         sid.....short id string (eg "R")
  134.  *         value...option value to OR with old tag's option value
  135.  * result: TRUE, if tag's option value updated
  136.  */
  137. static BOOL check_attr_option(HSCPRC * hp, STRPTR option, HSCATTR * attr, STRPTR id, STRPTR sid, ULONG value, ULONG unmasked_flags)
  138. {
  139.     BOOL found = FALSE;
  140.  
  141.     if (!((upstrcmp(option, id)) && (upstrcmp(option, sid))))
  142.     {
  143.  
  144.         DDA(fprintf(stderr, DHL "  option %s\n", id));
  145.  
  146.         if (value & unmasked_flags)
  147.         {
  148.  
  149.             hsc_message(hp, MSG_ILLG_ATTR_FLAG,
  150.                         "attribute flag %q not allowed in this context",
  151.                         id);
  152.  
  153.         }
  154.         else
  155.             attr->varflag |= value;
  156.  
  157.         found = TRUE;
  158.  
  159.     }
  160.  
  161.     return (found);
  162.  
  163. }
  164.  
  165. /*
  166.  * define_var
  167.  *
  168.  * define a new var with reading its def from input file
  169.  * (starts parsing after ":", so ":" has to be read before)
  170.  *
  171.  * params: varname..name of new var
  172.  *         varlist..list new var should be inserted at the beginning
  173.  *         inpf.....input file where to read def from
  174.  *         flag.....flags: VF_ONLYONCE to avoid re-definition of a var
  175.  * result: ptr to new var
  176.  *
  177.  * definition syntax in input file:
  178.  *   <vartype>[/flag]["="<deftext value>]
  179.  *   legal vartypes: see VT_STR_xx in "vars.h"
  180.  *   legal flags   : see VF_STR_xx in "vars.h"
  181.  */
  182. HSCATTR *define_var(HSCPRC * hp, DLLIST * varlist, ULONG unmasked_flags)
  183. {
  184.     HSCATTR *var = NULL;        /* result */
  185.     BOOL ok = FALSE;
  186.     BYTE val_vartype = VT_NONE; /* var-type (numeric) */
  187.     BOOL newattr = FALSE;       /* next word read from input */
  188.     STRPTR nw = NULL;
  189.     STRPTR varname = NULL;
  190.     BOOL eof_called = FALSE;    /* used at end-of-func, if nw==NULL */
  191.     INFILE *inpf = hp->inpf;
  192.  
  193.     /* read attribute name */
  194.     nw = infget_attrid(hp);
  195.     if (nw)
  196.     {
  197.         varname = strclone(nw); /* remember attribute name */
  198.     }
  199.     else
  200.         eof_called = TRUE;      /* err_eof() called already */
  201.  
  202.     /* read attribute type */
  203.     if (nw)
  204.         if (parse_wd(hp, ":"))
  205.         {
  206.             nw = infgetw(inpf);
  207.             if (nw)
  208.                 val_vartype = str2vartype(nw);
  209.         }
  210.         else
  211.             inungetcw(inpf);
  212.  
  213.     if (nw)
  214.     {
  215.         /*
  216.          * look if attr already exist;
  217.          * if yes, clear old attribute
  218.          * to redefine the new one
  219.          */
  220.         var = find_varname(varlist, varname);
  221.         if (var)
  222.         {
  223.             DLNODE *nd = find_attrnode(varlist, varname);
  224.  
  225.             /* remove old attribute */
  226.             if (nd)
  227.                 del_dlnode(varlist, nd);
  228.             else
  229.                 panic("no node for redefined attribute");
  230.  
  231.             hsc_message(hp, MSG_ATTR_REDEFINED,
  232.                         "redefined %a", varname);
  233.         }
  234.  
  235.         /*
  236.          * create new attribute
  237.          */
  238.         DDA(fprintf(stderr, DHL "new attr: %s\n", varname));
  239.         var = app_var(varlist, varname);
  240.  
  241.         /* set type */
  242.         var->vartype = val_vartype;
  243.         if (var->vartype == VT_ENUM)
  244.         {
  245.             /* init enum-attribute */
  246.             read_enum_str(hp, var);
  247.         }
  248.         else if (var->vartype == VT_BOOL)
  249.         {
  250.             /* init boolean attr with FALSE */
  251.             set_varbool(var, FALSE);
  252.         }
  253.  
  254.         newattr = TRUE;
  255.  
  256.     }
  257.  
  258.     /* disable "/STRIPEXT" and "/GETSIZE" for non-URI-attributes */
  259.     if (nw)
  260.     {
  261.         if (var->vartype != VT_URI)
  262.             unmasked_flags |= VF_GETSIZE | VF_STRIPEXT;
  263.  
  264.         nw = infgetw(inpf);     /* get net word */
  265.     }
  266.  
  267.     /*
  268.      * handle attribute flags
  269.      */
  270.     while (nw && !strcmp(nw, "/"))
  271.     {
  272.         nw = infgetw(inpf);     /* read flag identifier */
  273.         if (nw)
  274.         {
  275.             BOOL ok = FALSE;
  276.  
  277.             ok |= check_attr_option(hp, nw, var,
  278.                                     VF_CONST_STR, VF_CONST_SHT,
  279.                                     VF_CONST, unmasked_flags);
  280.             ok |= check_attr_option(hp, nw, var,
  281.                                     VF_GLOBAL_STR, VF_GLOBAL_SHT,
  282.                                     VF_GLOBAL, unmasked_flags);
  283.             ok |= check_attr_option(hp, nw, var,
  284.                                     VF_JERK_STR, VF_JERK_SHT,
  285.                                     VF_JERK, unmasked_flags);
  286.             ok |= check_attr_option(hp, nw, var,
  287.                                     VF_ONLYONCE_STR, VF_ONLYONCE_SHT,
  288.                                     VF_ONLYONCE, unmasked_flags);
  289.             ok |= check_attr_option(hp, nw, var,
  290.                                     VF_REQUIRED_STR, VF_REQUIRED_SHT,
  291.                                     VF_REQUIRED, unmasked_flags);
  292.             ok |= check_attr_option(hp, nw, var,
  293.                                     VF_GETSIZE_STR, VF_GETSIZE_SHT,
  294.                                     VF_GETSIZE, unmasked_flags);
  295.             ok |= check_attr_option(hp, nw, var,
  296.                                     VF_STRIPEXT_STR, VF_STRIPEXT_SHT,
  297.                                     VF_STRIPEXT, unmasked_flags);
  298.             if (!ok)
  299.             {
  300.                 hsc_message(hp, MSG_UNKN_ATTR_OPTION,
  301.                             "unknown attribute flag %q", nw);
  302.             }
  303.  
  304.             /* read next word (should be "/", "=" or next attr / ">") */
  305.             nw = infgetw(inpf);
  306.         }
  307.         else
  308.             hsc_msg_eof(hp, "defining attribute");
  309.  
  310.     }
  311.  
  312.     /*
  313.      * handle default value
  314.      */
  315.     if (nw && !strcmp(nw, "="))
  316.     {
  317.         /* get new deftext value */
  318.         STRPTR new_deftext = NULL;
  319.         LONG old_attrflag = var->varflag;
  320.  
  321.         /* disable quotemode-checking */
  322.         var->varflag |= VF_KEEP_QUOTES;
  323.  
  324.         if (!(var->deftext))
  325.             new_deftext = eval_expression(hp, var, NULL);
  326.         else
  327.         {
  328.             STRPTR dummy;
  329.  
  330.             hsc_message(hp, MSG_SYMB_2ND_DEFAULT,
  331.                         "default value for %A already set", var);
  332.  
  333.             /* skip illegal default value */
  334.             dummy = eval_expression(hp, var, NULL);
  335.         }
  336.  
  337.         /* restore quotemode-checking */
  338.         var->varflag = old_attrflag;
  339.  
  340.         /* store default text value */
  341.         if (new_deftext)
  342.             var->deftext = strclone(new_deftext);
  343.  
  344.         /* read next word, only to be ungotten below */
  345.         nw = infgetw(inpf);
  346.     }
  347.  
  348.     /* check for unexpected end of file */
  349.     if (!nw)
  350.     {
  351.         if (!eof_called)
  352.             hsc_msg_eof(hp, "defining attribute");
  353.     }
  354.     else
  355.     {
  356.         /* end of var definition reached */
  357.         inungetcw(inpf);
  358.         ok = TRUE;
  359.     }
  360.  
  361.     /* cleanup */
  362.     if (!ok && var)
  363.     {
  364.         DLNODE *nd = find_attrnode(varlist,varname);
  365.         if (nd)
  366.             del_dlnode(varlist, (APTR) nd);
  367.         else
  368.             del_hscattr(var);
  369.         var = NULL;
  370.     }
  371.     ufreestr(varname);
  372.  
  373.     return (var);
  374. }
  375.  
  376. /*
  377.  *-------------------------------------
  378.  * copy & remove local vars to/from
  379.  * global varlist
  380.  *-------------------------------------
  381.  */
  382.  
  383. /*
  384.  * copy_local_var
  385.  *
  386.  * copies a local attribute to the global attribute list
  387.  *
  388.  * NOTE: the VF_MACRO-flag of the copy is disabled!
  389.  */
  390. static HSCATTR *copy_local_var(DLLIST * destlist, HSCATTR * locvar, ULONG mci)
  391. {
  392.     HSCATTR *var = app_var(destlist, locvar->name);
  393.  
  394.     var->macro_id = mci;
  395.     var->vartype = locvar->vartype;
  396.     var->varflag = locvar->varflag & (~VF_MACRO);       /* disable VF_MACRO */
  397.     set_vartext(var, locvar->text);
  398.     var->quote = locvar->quote;
  399.  
  400.     return (var);
  401. }
  402.  
  403. /*
  404.  * copy_local_vars
  405.  *
  406.  * add all local attributes of a macro to the global
  407.  * attribute list.
  408.  *
  409.  */
  410. BOOL copy_local_varlist(DLLIST * destlist, DLLIST * varlist, ULONG mci)
  411. {
  412.     BOOL ok = TRUE;
  413.  
  414.     if (mci == MCI_ERROR)
  415.         panic("mci=MCI_ERROR");
  416.     else
  417.     {
  418.         DLNODE *nd = varlist->first;
  419.         HSCATTR *var;
  420.  
  421.         while (nd && ok)
  422.         {
  423.             var = copy_local_var(destlist, (HSCATTR *) (nd->data), mci);
  424.             ok &= (BOOL) (var != NULL);
  425.             nd = nd->next;
  426.         }
  427.     }
  428.  
  429.     return (ok);
  430. }
  431.  
  432. /*
  433.  * set_local_var
  434.  *
  435.  * copies a local attribute to the global attribute list
  436.  *
  437.  * NOTE: the VF_MACRO-flag of the set is enabled!
  438.  */
  439. static HSCATTR *set_local_var(DLLIST * destlist, HSCATTR * locvar, ULONG mci)
  440. {
  441.     HSCATTR *var = find_varname(destlist, locvar->name);
  442.  
  443.     if (var)
  444.     {
  445.         var->macro_id = mci;
  446.         var->vartype = locvar->vartype;
  447.         set_vartext(var, locvar->text);
  448.     }
  449.     else
  450.         panic("set_local_var to UNKNOWN ATTR");
  451.  
  452.     return (var);
  453. }
  454.  
  455. /*
  456.  * set_local_vars
  457.  *
  458.  * add all local attributes of a macro to the global
  459.  * attribute list.
  460.  *
  461.  */
  462. BOOL set_local_varlist(DLLIST * destlist, DLLIST * varlist, ULONG mci)
  463. {
  464.     BOOL ok = TRUE;
  465.  
  466.     if (mci == MCI_ERROR)
  467.         panic("mci=MCI_ERROR");
  468.     else
  469.     {
  470.         DLNODE *nd = varlist->first;
  471.         HSCATTR *var;
  472.  
  473.         while (nd && ok)
  474.         {
  475.             var = set_local_var(destlist, (HSCATTR *) (nd->data), mci);
  476.             ok &= (BOOL) (var != NULL);
  477.             nd = nd->next;
  478.         }
  479.     }
  480.  
  481.     return (ok);
  482. }
  483.  
  484. /*
  485.  * remove_local_varlist
  486.  */
  487. VOID remove_local_varlist(DLLIST * varlist, ULONG mci)
  488. {
  489.     DLNODE *nd = varlist->first;
  490.  
  491.     while (nd)
  492.     {
  493.         HSCATTR *var = (HSCATTR *) nd->data;    /* var data of node */
  494.         DLNODE *nd_nxt = nd->next;      /* next node */
  495.  
  496.         if (var->macro_id == mci)
  497.             del_dlnode(varlist, nd);
  498.  
  499.         nd = nd_nxt;
  500.     }
  501. }
  502.  
  503.